$.fn.editArea = function () {
    var element = this;

    // get element size
    var eHeight = $(element).height();
    var eWidth = $(element).width();

    // get parent 
    var parent = element[0].parentNode

    // FLAGS
    var isLog = true;
    var isCanDraw = true;
    var isDraw = false;
    var isDrag = false;

    ////// VARIABLES FOR DRAWING NEW AREA \\\\\\
    // new area
    var area;
    // initial coordinate of new area
    var iX, iY;
    // whidth and height of new area
    var areaH, areaW;
    // final coordinate of new area
    var fX, fY;
    var aTop, aBottom, aLeft, aRight;

    ////// VARIABLES FOR DRAG AREA \\\\\\
    // initalize position of mouse
    var dragX, dragY;
    // area shift relative to the start position
    var dragShiftX, dragShiftY;

    // add panel to the container
    addPanel();

    // add to element right click event
    $(element).bind('contextmenu', contextMenu);
    $(element).bind('click', closeContextMenu);

    // find elemnt region
    var eLeft = $(element).offset().left;
    var eTop = $(element).offset().top;
    var eRight = eLeft + eWidth;
    var eBottom = eTop + eHeight;

    //////////////////////////// Panel \\\\\\\\\\\\\\\\\\\\\\\\
    function addPanel() {
        element[0].className = "element";

        // INSERT PANEL
        var panel = $(element).addItem({ id: 'panel', type: 'panel', element: 'div', appendBefore: true });
        // insert group box
        var group = $(panel).addItem({ className: 'group-box', type: 'group', element: 'span' });

        // ADD BUTONS TO PANEL
        // add pencel
        var item = $(group).addItem({
            id: 'pen',
            type: 'item',
            element: 'a',
            title: 'Pencil',
            eType: 'element',
            click: panelItemClick,
            cssText: 'border-bottom-left-radius:4px; border-top-left-radius:4px;'
        });

        // add strokethrough
        $(group).addItem({
            id: 'strokethrough',
            type: 'item',
            element: 'a',
            eType: 'action',
            title: 'Stroke Through',
            click: panelItemClick
        });

        // add text
        $(group).addItem({
            id: 'text',
            type: 'item',
            element: 'a',
            eType: 'element',
            title: 'Text',
            click: panelItemClick,
            cssText: 'border-bottom-right-radius:4px; border-top-right-radius:4px;'
        });
    }

    function panelItemClick(e) {
        // get element
        var item = $(this);
        var isActive = !item.hasClass('active-item');

        var elementType = item.attr('eType');
        if (elementType == 'element') {
            if (isActive) {
                // deactivate all active item
                $(".active-item").each(function (index) {
                    $(this).removeClass('active-item');

                    // deactivate draw functionality
                    if (this.id == 'pen')
                        deactivateDraw();

                });

                // set action state
                item.addClass('active-item');
            }
            else
                // remove action state
                item.removeClass('active-item');
        }

        // find action metod
        if (item.attr('id') == 'pen') {
            if (isActive)
                activateDraw();
            else
                deactivateDraw();
        }
    }

    function contextMenu(e) {
        $('#contextMenu').css({
            'top': e.pageY,
            'left': e.pageX
        });
        $('#contextMenu').removeClass('invisible');

        return false;
    }
    function closeContextMenu(e) {
        $('#contextMenu').css({
            'top': 0,
            'left': 0
        });
        $('#contextMenu').addClass('invisible');
    }

    ///////////////////////// Draw \\\\\\\\\\\\\\\\\\\\\\\\\
    function activateDraw() {
        // element instanse
        var editor = $(element);

        // unbind all event from editor
        editor.unbind();

        // bind draw events
        editor.bind("mousedown", startDraw);
        editor.bind("mousemove", drawing);
        editor.bind("mouseup", endDraw);
        //editor.bind("mouseout", endDragArea);
    }
    function deactivateDraw() {
        // unbind all event from editor
        $(element).unbind();
    }

    // bind mouse event on element
    function startDraw(e) {
        // check if we can draw new area
        if (!isCanDraw)
            return;

        log('\nStart draw new area');

        // set state that we start draw new area
        isDraw = true;

        // get initial coordinate of area
        iX = e.pageX
        iY = e.pageY

        // add new area to element
        $("#container").append("<div class='new-area' style='border:1px solid green; height: 0; width: 0; position: absolute; top:" + iY + "; left:" + iX + ";'></div>");

        // get area object
        area = $('.new-area');

        // show start poin
        log("iX&iY: " + iX + "x" + iY);
    }
    function drawing(e) {
        // check if we can draw new area
        if (!isDraw || !isCanDraw)
            return;

        // get final coordinate of new area
        fX = e.pageX;
        fY = e.pageY;

        // find area size
        areaH = Math.abs(iY - fY);
        areaW = Math.abs(iX - fX);

        // set area size
        area.height(areaH);
        area.width(areaW);

        // set area position by X
        if (fX < iX)
            area.css('left', fX + 'px');
        else
            area.css('left', iX + "px");

        // set area position by Y
        if (fY < iY)
            area.css('top', fY + 'px');
        else
            area.css('top', iY + 'px');
    }
    function endDraw(e) {
        // check if we can draw new area
        if (!isDraw || !isCanDraw)
            return;

        isDraw = false;

        // check if new area have min requirements
        if (area.height() > 5 || area.width() > 5) {
            // bind events to new area
            area.bind("mousedown", startDragArea);
            area.bind("mousemove", dragArea);
            area.bind("mouseup", endDragArea);
            area.bind("mouseout", endDragArea);

            // finish draw new area
            area.addClass('area');
            area.removeClass('new-area');

            log("fX&fY: " + fX + "x" + fY);
        }
        else {
            // delete element from editor
            area.remove();

            log('Element was deleted')
        }

        clear()

        log('End draw new area\n');
    }

    ///////////////////////// Drag \\\\\\\\\\\\\\\\\\\\\\\\\
    function startDragArea(e) {
        log('\nStart drag')
        isDrag = true;
        isCanDraw = false;

        //get area inst.
        area = $(this);

        area.addClass("drag-area");

        // find initialize position of area
        aLeft = area.offset().left;
        aTop = area.offset().top;
        aRight = aLeft + area.width();
        aBottom = aTop + area.height();

        // get mouse position
        dragX = e.pageX;
        dragY = e.pageY;
    }
    function dragArea(e) {
        if (!isDrag) return;

        // find shift by x and y
        dragShiftX = e.pageX - dragX;
        dragShiftY = e.pageY - dragY;

        // find new area coordinate
        var left = aLeft + dragShiftX;       // new x
        var top = aTop + dragShiftY;       // new y
        var bottom = area.height() + top;
        var right = area.width() + left;

        // top & bottom
        top = eTop > top ? eTop
            : eBottom < bottom ? (eBottom - area.height()) : top;
        $(this).css('top', top + 'px');

        // left & right
        left = eLeft > left ? eLeft
            : eRight < right ? (eRight - area.width()) : left;
        $(this).css('left', left + 'px');
    }
    function endDragArea(e) {
        if (!isDrag) return;

        // finish drag operation
        isDrag = false;
        isCanDraw = true;

        $(this).removeClass("drag-area");

        log('Shift by X: ' + dragShiftX);
        log('Shift by Y: ' + dragShiftY);

        clear();

        log('End drag\n');
    }


    ///////////////////////// End \\\\\\\\\\\\\\\\\\\\\\\\\

    // clear all variables
    function clear() {
        // draw area 
        areaH, areaW, fX, fY = 0;
        aTop, aBottom, aLeft, aRight = 0
        area = null;

        // drag area
        dragX, dragY, dragShiftX, dragShiftY = 0;
    }

    function log(text) {
        if (isLog)
            console.log(text);
    }
};

$.fn.addItem = function (options) {
    var element = this;

    // This is the easiest way to have default options.
    var settings = $.extend({
        // defaults
        element: 'div',
        id: '',
        className: '',
        cssText: "",
        title: '',
        appendBefore: false,
        type: '',
        click: '',
        eType: '',
    }, options);

    // check if have all requirements
    if (settings.type == '') return false;

    // initialize item
    var item = document.createElement(settings.element);
    // set element id
    if (settings.id != '')
        item.id = settings.id;
    // set element style
    if (settings.cssText != '')
        item.style.cssText = settings.cssText;
    // set element class
    if (settings.className != '')
        item.className = settings.className;
    // set element title
    if (settings.title != '')
        item.setAttribute('title', settings.title);
    // set onclick event
    if (settings.click)
        $(item).bind("click", settings.click);
    // set element type
    if (settings.eType != '')
        item.setAttribute('eType', settings.eType);


    if (settings.type == 'item') {
        // add spot to item
        item.appendChild(document.createElement('span'));
    }

    if (settings.appendBefore) {
        // get element parent
        var parent = element[0].parentNode
        // add item to parent
        parent.insertBefore(item, element[0]);
    }
    else {
        // add item to element
        element[0].appendChild(item);
    }

    return item;
}